#ifndef	__ASSEMBLER__
#define	__ASSEMBLER__
#endif

#include <layout.h>
#include <mmu.h>
		
#include "kernel.S.h"
		
		// The ASM part of the kernel
			  
#define	SRL(val, shamt)	(((val) >> (shamt)) & ~(-1 << (32 - (shamt))))

		.globl vpd_lock
		.set	vpd_lock, VPDLCK
		.globl lapic
		.set	lapic, LAPIC
		.globl vpt
		.set	vpt, KVPT
		.globl vpd
		.set	vpd, (KVPT + SRL(KVPT, 10))

		.globl delay
delay:
		inb	$0x84, %al
		inb	$0x84, %al
		inb	$0x84, %al
		inb	$0x84, %al

		ret

		.globl reboot
reboot:	
		// If the kernel is over, do a rebooting
		// warm reboot.
		// change it to ``movw $0x0000, 0x472'' if you want cold rebooting
		
		movw $0x1234, 0x472
		ljmp $0xf000,$0xfff0

		.globl get_tpage
get_tpage:
		movl	%esp, %eax
		orl     $(KSTACK_SIZE - 1), %eax
		xorl	$(KSTACK_SIZE - 1), %eax
		ret

		// Get the current process id by the offset of stack pointer
		.globl cur_proc_id
cur_proc_id:
		movl	%esp, %eax
		xor		$KSTACK, %eax
		shr		$KSTACK_SHIFT, %eax
		ret

		#if 0
		// Get the current process struct directly
		.globl cur_proc
cur_proc:	
		movl	%esp, %eax
		xor		$KSTACK, %eax
		shr		$KSTACK_SHIFT, %eax
		shl   	$PROC_STRUCT_SIZE_SHIFT, %eax
		addl    $procs, %eax
		ret
		#endif

		// routine for jump to user mode
		// jump_user(addr, stack, eflags)
		.globl jump_user
jump_user:
		// Here we use esp to get the parameter
		movl	%ss:4(%esp), %edx
		movl    %ss:8(%esp), %ebx
		movl	%ss:12(%esp), %ecx
		
		cli
		movl	$GD_USER_DATA, %eax
		orw		$3, %ax
		movw	%ax, %ds
		movw	%ax, %es
		movw	%ax, %fs
		movw	%ax, %gs

		// use the uxstack
		pushl	%eax
		pushl	%ebx
		
		pushl	%ecx
		
		movl	$GD_USER_TEXT, %eax
		orw		$3, %ax
		pushl	%eax
		pushl	%edx
		iret

		//	The macro that make kernel user call back return point
		.macro set_kcb_ret_point
		pushl	%ebp
		movl	%esp, %ebp
		
		pushl	%ds
		pushl	%es
		pusha
		pushf

		call	cur_cpu
		shl		$TS_USHIFT, %eax
		pushl	(tasks_start + TS_ESP0_OFFSET)(%eax)
		movl	%esp, (tasks_start + TS_ESP0_OFFSET)(%eax)
		.endm
		
		//	Return to the return point of kernel user call
		.macro do_kcb_ret rv

		pushl	\rv
		call	cur_cpu
		popl	%ebx
		shl		$TS_USHIFT, %eax
		
		movl	(tasks_start + TS_ESP0_OFFSET)(%eax), %esp
		popl	(tasks_start + TS_ESP0_OFFSET)(%eax)
		
		popf
		
		movl	%ebx, %ss:28(%esp)
		popa
		
		//	xchg  %bx, %bx
		
		popl	%es
		popl	%ds
		popl	%ebp
		ret
		.endm

		// call to the user with return
		//	(entry, stack, flags)
		.globl call_user
call_user:
		set_kcb_ret_point
		
		movl	%ss:8(%ebp), %ebx
		movl	%ss:12(%ebp), %edx
		movl    %ss:16(%ebp), %ecx
		
		movl	$GD_USER_DATA, %eax
		orw		$3, %ax
		movw	%ax, %ds
		movw	%ax, %es
		
		pushl	%eax
		pushl	%edx
		
		pushl	%ecx
		
		movl	$GD_USER_TEXT, %eax
		orw		$3, %ax
		pushl	%eax
		pushl	%ebx
		
		iret

		.globl kcb_ret
kcb_ret:
		do_kcb_ret %eax

		// macro that produce interrupt processing code
		.macro isr_noerr n
		
		.globl isr\n
isr\n:
		
		pushl $0
		pushl $\n
		
		
		jmp	isr_common_handler
		
		.endm
		
		// isr that generates err no
		.macro isr_err n
		
		.globl isr\n
isr\n:
		pushl $\n

		jmp	isr_common_handler

		.endm

		// call timer IRQ0

		.globl call_irq0
call_irq0:
		int	$PICV_OFFSET1
		ret

		// call yield interruption
		.globl call_yield
call_yield:
		int	$INT_YIELD
		ret
		
		// irq processing
		.macro irq i
		.globl irq\i
irq\i:
		pushl	$0
		pushl	$\i
		jmp	irq_common_handler
		
		.endm
		
		// the generated code
		
		isr_noerr	0
		isr_noerr	1
		isr_noerr	2
		isr_noerr	3
		isr_noerr	4
		isr_noerr	5
		isr_noerr	6
		isr_noerr	7
		isr_err 8
		isr_noerr	9
		isr_err 10
		isr_err 11
		isr_err 12
		isr_err 13
		isr_err 14
		isr_noerr	15
		isr_noerr	16
		isr_noerr	17
		isr_noerr	18
		isr_noerr	19
		isr_noerr	20
		isr_noerr	21
		isr_noerr	22
		isr_noerr	23
		isr_noerr	24
		isr_noerr	25
		isr_noerr	26
		isr_noerr	27
		isr_noerr	28
		isr_noerr	29
		isr_noerr	30
		isr_noerr	31

		isr_noerr 32
		isr_noerr 33
		isr_noerr 34
		isr_noerr 35
		isr_noerr 36
		isr_noerr 37
		isr_noerr 38
		isr_noerr 39
		isr_noerr 40
		isr_noerr 41
		isr_noerr 42
		isr_noerr 43
		isr_noerr 44
		isr_noerr 45
		isr_noerr 46
		isr_noerr 47
		isr_noerr 48
		isr_noerr 49
		isr_noerr 50
		isr_noerr 51
		isr_noerr 52
		isr_noerr 53
		isr_noerr 54
		isr_noerr 55
		isr_noerr 56
		isr_noerr 57
		isr_noerr 58
		isr_noerr 59
		isr_noerr 60
		isr_noerr 61
		isr_noerr 62
		isr_noerr 63
		isr_noerr 64
		isr_noerr 65
		isr_noerr 66
		isr_noerr 67
		isr_noerr 68
		isr_noerr 69
		isr_noerr 70
		isr_noerr 71
		isr_noerr 72
		isr_noerr 73
		isr_noerr 74
		isr_noerr 75
		isr_noerr 76
		isr_noerr 77
		isr_noerr 78
		isr_noerr 79
		isr_noerr 80
		isr_noerr 81
		isr_noerr 82
		isr_noerr 83
		isr_noerr 84
		isr_noerr 85
		isr_noerr 86
		isr_noerr 87
		isr_noerr 88
		isr_noerr 89
		isr_noerr 90
		isr_noerr 91
		isr_noerr 92
		isr_noerr 93
		isr_noerr 94
		isr_noerr 95
		isr_noerr 96
		isr_noerr 97
		isr_noerr 98
		isr_noerr 99
		isr_noerr 100
		isr_noerr 101
		isr_noerr 102
		isr_noerr 103
		isr_noerr 104
		isr_noerr 105
		isr_noerr 106
		isr_noerr 107
		isr_noerr 108
		isr_noerr 109
		isr_noerr 110
		isr_noerr 111
		isr_noerr 112
		isr_noerr 113
		isr_noerr 114
		isr_noerr 115
		isr_noerr 116
		isr_noerr 117
		isr_noerr 118
		isr_noerr 119
		isr_noerr 120
		isr_noerr 121
		isr_noerr 122
		isr_noerr 123
		isr_noerr 124
		isr_noerr 125
		isr_noerr 126
		isr_noerr 127
		isr_noerr 128
		isr_noerr 129
		isr_noerr 130
		isr_noerr 131
		isr_noerr 132
		isr_noerr 133
		isr_noerr 134
		isr_noerr 135
		isr_noerr 136
		isr_noerr 137
		isr_noerr 138
		isr_noerr 139
		isr_noerr 140
		isr_noerr 141
		isr_noerr 142
		isr_noerr 143
		isr_noerr 144
		isr_noerr 145
		isr_noerr 146
		isr_noerr 147
		isr_noerr 148
		isr_noerr 149
		isr_noerr 150
		isr_noerr 151
		isr_noerr 152
		isr_noerr 153
		isr_noerr 154
		isr_noerr 155
		isr_noerr 156
		isr_noerr 157
		isr_noerr 158
		isr_noerr 159
		isr_noerr 160
		isr_noerr 161
		isr_noerr 162
		isr_noerr 163
		isr_noerr 164
		isr_noerr 165
		isr_noerr 166
		isr_noerr 167
		isr_noerr 168
		isr_noerr 169
		isr_noerr 170
		isr_noerr 171
		isr_noerr 172
		isr_noerr 173
		isr_noerr 174
		isr_noerr 175
		isr_noerr 176
		isr_noerr 177
		isr_noerr 178
		isr_noerr 179
		isr_noerr 180
		isr_noerr 181
		isr_noerr 182
		isr_noerr 183
		isr_noerr 184
		isr_noerr 185
		isr_noerr 186
		isr_noerr 187
		isr_noerr 188
		isr_noerr 189
		isr_noerr 190
		isr_noerr 191
		isr_noerr 192
		isr_noerr 193
		isr_noerr 194
		isr_noerr 195
		isr_noerr 196
		isr_noerr 197
		isr_noerr 198
		isr_noerr 199
		isr_noerr 200
		isr_noerr 201
		isr_noerr 202
		isr_noerr 203
		isr_noerr 204
		isr_noerr 205
		isr_noerr 206
		isr_noerr 207
		isr_noerr 208
		isr_noerr 209
		isr_noerr 210
		isr_noerr 211
		isr_noerr 212
		isr_noerr 213
		isr_noerr 214
		isr_noerr 215
		isr_noerr 216
		isr_noerr 217
		isr_noerr 218
		isr_noerr 219
		isr_noerr 220
		isr_noerr 221
		isr_noerr 222
		isr_noerr 223
		isr_noerr 224
		isr_noerr 225
		isr_noerr 226
		isr_noerr 227
		isr_noerr 228
		isr_noerr 229
		isr_noerr 230
		isr_noerr 231
		isr_noerr 232
		isr_noerr 233
		isr_noerr 234
		isr_noerr 235
		isr_noerr 236
		isr_noerr 237
		isr_noerr 238
		isr_noerr 239
		isr_noerr 240
		isr_noerr 241
		isr_noerr 242
		isr_noerr 243
		isr_noerr 244
		isr_noerr 245
		isr_noerr 246
		isr_noerr 247
		isr_noerr 248
		isr_noerr 249
		isr_noerr 250
		isr_noerr 251
		isr_noerr 252
		isr_noerr 253
		isr_noerr 254
		isr_noerr 255

		// generate the task switching code
		// these code assumes that interrupt has been disabled
		.macro switching_trigger name
		
		pushl	%ds
		pushl	%es
		pusha
		
		movl	%esp, %eax
		pushl	%eax
		
		//	call the real switch handler
		call	st_handler
				
		// Check the return value to decide whether to switch 
		cmpl	$0, %eax

		je	st_not_switch_\name
				
		movl	%eax, %cr3
		
st_not_switch_\name:
		
		popl	%eax
		movl	%eax, %esp
		
		//	after the switching
		//	may handle the signal
		call	after_switching_hook
		
		popa
		
		//	xchg  %bx, %bx
		
		popl	%es
		popl	%ds
		
		.endm
		
		//	irq 0 the trigger
irq0:
		
		pushl	$0
		pushl	$0
		
		switching_trigger irq0
		
		//	clear the pushed err no(empty) and irq number
		addl	$8, %esp
		iret
		
		//	int_yield the trigger
		.global int_yield
		
int_yield:
		
		pushl	$0
		pushl	$INT_YIELD
		
		switching_trigger int_yield
		
		//	clear the pushed err no(empty) and irq number
		addl	$8, %esp
		iret
				
		irq	1
		irq	2
		irq	3
		irq	4
		irq	5
		irq	6
		irq	7
		irq	8
		irq	9
		irq	10
		irq	11
		irq	12
		irq	13
		irq	14
		irq	15
		irq	16
		irq	17
		irq	18
		irq	19
		irq	20
		irq	21
		irq	22
		irq	23
		irq	24
		irq	25
		irq	26
		irq	27
		irq	28
		irq	29
		irq	30
		irq	31
		
isr_common_handler:
		
		pushl	%ds
		pushl	%es
		pusha
		
		//	call the real handler
		
		call	kexception
		
		//	clear the pushed err no and isr number
		
		popa
		//	xchg  %bx, %bx
		popl	%es
		popl	%ds
		
		addl	$8, %esp
		iret
		
irq_common_handler:
		
		pushl	%ds
		pushl	%es
		pusha
		
		//	call the real handler
		call	kirq
		
		//	clear the pushed err no(empty) and irq number
		popa
		//	xchg  %bx, %bx
		popl	%es
		popl	%ds
		
		addl	$8, %esp
		iret
		
		.globl syscall
syscall:
		pushl	$0x0
		pushl	%eax
		pushl	%ds
		pushl	%es
		pusha
		
		call	syscall_handler
		
		popa
		//	xchg  %bx, %bx
		
		popl	%es
		popl	%ds
		
		addl	$8, %esp
		iret

		.globl ipi
ipi:
		pushl	$0x0
		pushl	%eax
		pushl	%ds
		pushl	%es
		pusha
		
		call	ipi_handler
		
		popa
		//	xchg  %bx, %bx
		
		popl	%es
		popl	%ds
		
		addl	$8, %esp
		iret
		
		.data
		
		.globl isr
isr:
		.long	isr0
		.long	isr1
		.long	isr2
		.long	isr3
		.long	isr4
		.long	isr5
		.long	isr6
		.long	isr7
		.long	isr8
		.long	isr9
		.long	isr10
		.long	isr11
		.long	isr12
		.long	isr13
		.long	isr14
		.long	isr15
		.long	isr16
		.long	isr17
		.long	isr18
		.long	isr19
		.long	isr20
		.long	isr21
		.long	isr22
		.long	isr23
		.long	isr24
		.long	isr25
		.long	isr26
		.long	isr27
		.long	isr28
		.long	isr29
		.long	isr30
		.long	isr31
		
		.long isr32
		.long isr33
		.long isr34
		.long isr35
		.long isr36
		.long isr37
		.long isr38
		.long isr39
		.long isr40
		.long isr41
		.long isr42
		.long isr43
		.long isr44
		.long isr45
		.long isr46
		.long isr47
		.long isr48
		.long isr49
		.long isr50
		.long isr51
		.long isr52
		.long isr53
		.long isr54
		.long isr55
		.long isr56
		.long isr57
		.long isr58
		.long isr59
		.long isr60
		.long isr61
		.long isr62
		.long isr63
		.long isr64
		.long isr65
		.long isr66
		.long isr67
		.long isr68
		.long isr69
		.long isr70
		.long isr71
		.long isr72
		.long isr73
		.long isr74
		.long isr75
		.long isr76
		.long isr77
		.long isr78
		.long isr79
		.long isr80
		.long isr81
		.long isr82
		.long isr83
		.long isr84
		.long isr85
		.long isr86
		.long isr87
		.long isr88
		.long isr89
		.long isr90
		.long isr91
		.long isr92
		.long isr93
		.long isr94
		.long isr95
		.long isr96
		.long isr97
		.long isr98
		.long isr99
		.long isr100
		.long isr101
		.long isr102
		.long isr103
		.long isr104
		.long isr105
		.long isr106
		.long isr107
		.long isr108
		.long isr109
		.long isr110
		.long isr111
		.long isr112
		.long isr113
		.long isr114
		.long isr115
		.long isr116
		.long isr117
		.long isr118
		.long isr119
		.long isr120
		.long isr121
		.long isr122
		.long isr123
		.long isr124
		.long isr125
		.long isr126
		.long isr127
		.long isr128
		.long isr129
		.long isr130
		.long isr131
		.long isr132
		.long isr133
		.long isr134
		.long isr135
		.long isr136
		.long isr137
		.long isr138
		.long isr139
		.long isr140
		.long isr141
		.long isr142
		.long isr143
		.long isr144
		.long isr145
		.long isr146
		.long isr147
		.long isr148
		.long isr149
		.long isr150
		.long isr151
		.long isr152
		.long isr153
		.long isr154
		.long isr155
		.long isr156
		.long isr157
		.long isr158
		.long isr159
		.long isr160
		.long isr161
		.long isr162
		.long isr163
		.long isr164
		.long isr165
		.long isr166
		.long isr167
		.long isr168
		.long isr169
		.long isr170
		.long isr171
		.long isr172
		.long isr173
		.long isr174
		.long isr175
		.long isr176
		.long isr177
		.long isr178
		.long isr179
		.long isr180
		.long isr181
		.long isr182
		.long isr183
		.long isr184
		.long isr185
		.long isr186
		.long isr187
		.long isr188
		.long isr189
		.long isr190
		.long isr191
		.long isr192
		.long isr193
		.long isr194
		.long isr195
		.long isr196
		.long isr197
		.long isr198
		.long isr199
		.long isr200
		.long isr201
		.long isr202
		.long isr203
		.long isr204
		.long isr205
		.long isr206
		.long isr207
		.long isr208
		.long isr209
		.long isr210
		.long isr211
		.long isr212
		.long isr213
		.long isr214
		.long isr215
		.long isr216
		.long isr217
		.long isr218
		.long isr219
		.long isr220
		.long isr221
		.long isr222
		.long isr223
		.long isr224
		.long isr225
		.long isr226
		.long isr227
		.long isr228
		.long isr229
		.long isr230
		.long isr231
		.long isr232
		.long isr233
		.long isr234
		.long isr235
		.long isr236
		.long isr237
		.long isr238
		.long isr239
		.long isr240
		.long isr241
		.long isr242
		.long isr243
		.long isr244
		.long isr245
		.long isr246
		.long isr247
		.long isr248
		.long isr249
		.long isr250
		.long isr251
		.long isr252
		.long isr253
		.long isr254
		.long isr255

		.globl irq
irq:	
		.long	irq0
		.long	irq1
		.long	irq2
		.long	irq3
		.long	irq4
		.long	irq5
		.long	irq6
		.long	irq7
		.long	irq8
		.long	irq9
		.long	irq10
		.long	irq11
		.long	irq12
		.long	irq13
		.long	irq14
		.long	irq15
		.long	irq16	
		.long	irq17
		.long	irq18
		.long	irq19
		.long	irq20
		.long	irq21
		.long	irq22
		.long	irq23
		.long	irq24
		.long	irq25
		.long	irq26
		.long	irq27
		.long	irq28
		.long	irq29
		.long	irq30
		.long	irq31
	
		.globl kstack_alloc
		.set kstack_alloc, KSTACK_ALLOC
		
		.globl dyninfo
		.set dyninfo, DYNINFO

		.align PAGE_SIZE
		.globl tasks_start
tasks_start:
		.space SMP_MAX_COUNT * TS_USIZE
		
		.align PAGE_SIZE * 2
		.globl klog_pipe
		// the kernel log pipe
klog_pipe:
		.space PAGE_SIZE * 2

		
		.align 1
		//	include the user lib code here
		.globl user_lib
		.globl user_lib_end
user_lib:
#include "user_image.S"
user_lib_end:
